#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "semaphore.h"

typedef int (*process)(void *arg);

pid_t create_process(process entry, void *arg)
{
	int exit_value;
	pid_t pid;
	
	if(!entry)
		return -1;
	
	//创建子进程
	pid = fork();
	if(pid == 0)
	{
		//fork在子进程中返回0
		exit_value = entry(arg);
		exit(exit_value);
	}
	//fork在父进程中返回子进程的ID
	return pid;
}

int read_process(void *arg)
{
	int shm_id;
	int read_sem;
	int write_sem;
	key_t key;
	char *shm;
	
	//生成key值
	key = ftok("/", 0);
	if(key == -1)
	{
		perror("ftok");
		return -1;
	}

	//创建或打开同步信号量
	read_sem = semaphore_create("/", 0);
	if(read_sem == -1)
	{
		perror("semaphore_create");
		return -1;
	}
	write_sem = semaphore_create("/", 1);
	if(write_sem == -1)
	{
		perror("semaphore_create");
		return -1;
	}
	
	//创建或获取共享内存
	key = ftok("./", 0);
	if(key == -1)
	{
		perror("ftok");
		return -1;
	}
	shm_id = shmget(key, 1024, IPC_CREAT|0666);
	if(shm_id == -1)
	{
		perror("shmget");
		return -1;
	}
	//映射共享内存
	shm = shmat(shm_id, NULL, 0);
	if(shm == (void*)-1)
	{
		perror("shmat");
		return -1;
	}
	
	while(1)
	{
		//等待内存可读
		semaphore_wait(read_sem);
		//写共享内存
		printf("%s", shm);
		//设置为可写
		semaphore_post(write_sem);
	}
}

int write_process(void *arg)
{
	int i;
	int shm_id;
	int read_sem;
	int write_sem;
	key_t key;
	char *shm;

	//创建或打开同步信号量
	read_sem = semaphore_create("/", 0);
	if(read_sem == -1)
	{
		perror("semaphore_create");
		return -1;
	}
	write_sem = semaphore_create("/", 1);
	if(write_sem == -1)
	{
		perror("semaphore_create");
		return -1;
	}
	
	//创建或获取共享内存
	key = ftok("./", 0);
	if(key == -1)
	{
		perror("ftok");
		return -1;
	}
	shm_id = shmget(key, 1024, IPC_CREAT|0666);
	if(shm_id == -1)
	{
		perror("shmget");
		return -1;
	}
	//映射共享内存
	shm = shmat(shm_id, NULL, 0);
	if(shm == (void*)-1)
	{
		perror("shmat");
		return -1;
	}
	
	i=0;
	while(1)
	{
		i++;
		
		//等待内存可写
		semaphore_wait(write_sem);
		//写共享内存
		memset(shm, 0, 1024);
		snprintf(shm, 1024, "message test,%d\r\n", i);
		//设置为可读
		semaphore_post(read_sem);
		
		sleep(1);
	}
}

int main(int argv, char *argc[])
{
	int read_sem;
	int write_sem;
	pid_t pid1,pid2;
	
	//创建或打开同步信号量
	read_sem = semaphore_create("/", 0);
	if(read_sem == -1)
	{
		perror("semaphore_create");
		return -1;
	}
	write_sem = semaphore_create("/", 1);
	if(write_sem == -1)
	{
		perror("semaphore_create");
		return -1;
	}

	//初始化为可写
	if(semaphore_set_value(write_sem, 1) == -1)
	{
		perror("semaphore_set_value");
		return -1;
	}
	//初始化为不可读
	if(semaphore_set_value(read_sem, 0) == -1)
	{
		perror("semaphore_set_value");
		return -1;
	}
	
	//同时创建的进程其执行的先后顺序不确定
	pid1 = create_process(read_process, "read_process;");
	printf("read_process PID=%d\r\n", pid1);
	
	pid2 = create_process(write_process, "write_process;");
	printf("write_process PID=%d\r\n", pid2);
	
	while(1)
	{
		sleep(10);
	}
}
